package spring.cloud.tasks.executor.listener.sharding;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.api.CuratorWatcher;
import org.apache.zookeeper.WatchedEvent;
import spring.cloud.tasks.executor.utils.log.LogUtils;

/**
 * curator在注册watch事件上，提供了一个usingWatcher方法，使用这个方法注册的watch事件和默认watch事件一样，监听只会触发一次，监听完毕后就会销毁，也就是一次性的。而这个方法有两种参数可选，一个是zk原生API的Watcher接口的实现类，另一个是Curator提供的CuratorWatcher接口的实现类，不过在usingWatcher方法上使用哪一个效果都是一样的，都是一次性的。
 */
@Slf4j
@Setter
@Getter
class NecessaryCuratorWatcher implements CuratorWatcher {

    private final ShardingListenerHolder shardingListenerHolder;

    public NecessaryCuratorWatcher(ShardingListenerHolder shardingListenerHolder) {
        this.shardingListenerHolder = shardingListenerHolder;
    }

    @Override
    public void process(WatchedEvent watchedEvent) throws Exception {
        if (shardingListenerHolder.isShutdown) {
            return;
        }
        switch (watchedEvent.getType()) {
            case NodeCreated:
            case NodeDataChanged: // NOSONAR
                LogUtils.info(log, shardingListenerHolder.getTaskId(), "event type:{}, path:{}", watchedEvent.getType(), watchedEvent.getPath());
                shardingListenerHolder.doBusiness();
            default:
                // use the thread pool to executor registerNecessaryWatcher by async,
                // fix the problem:
                // when zk is reconnected, this watcher thread is earlier than the notice of RECONNECTED EVENT,
                // registerNecessaryWatcher will wait until reconnected or timeout,
                // the drawback is that this watcher thread will block the notice of RECONNECTED EVENT.
                shardingListenerHolder.registerNecessaryWatcher();
        }
    }

}
